package testing;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Random;

import com.thesis.algorithm.FileConverter;
import com.thesis.algorithm.Sequence;
import com.thesis.algorithm.SequenceElement;
import com.thesis.algorithm.SequenceMatching;
import com.thesis.utils.BusControl;
import com.thesis.utils.CONSTANTS;
import com.thesis.utils.Utils;

public class BusrouteMatchingWrapper {
	LinkedList<Sequence> _TESTDATA = new LinkedList<Sequence>();
	SequenceMatching sm = new SequenceMatching(
			SequenceMatching.MODE_READ_FROM_TRAINFOLDER);

	public BusrouteMatchingWrapper() {
		// TODO Auto-generated constructor stub
		BusControl busController = new BusControl();
		FileConverter fc = new FileConverter(CONSTANTS.TEST_DATA_FOLDER);
		_TESTDATA = busController.produceTrainSequence(fc.listOfDevices);
		for (int i = 0; i < _TESTDATA.size(); i++) {
			System.out.println("TESTDATA" + _TESTDATA.get(i).BusRouteID + " "
					+ _TESTDATA.get(i).size());
		}
	}

	public void testBusStopAndPrintToFile(int sequence_length,
			Writer outSummary, Writer outExcel) {

		try {
			Writer out = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(CONSTANTS.RESULT_FOLDER
							+ "busstopmatching_sequenceLength"
							+ sequence_length + ".txt"), "UTF-8"));

			int countFalse = 0;
			int confusedCase = 0;
			Random randomGenerator = new Random();

			for (int i = 0; i < CONSTANTS.nExample; i++) {

				// test data
				int fileindex = randomGenerator.nextInt(_TESTDATA.size()) - 1;
				if (fileindex == -1) {
					fileindex = 0;
				}

				int start = randomGenerator.nextInt(_TESTDATA.get(fileindex)
						.size() - sequence_length - 1);
				Sequence testdata = new Sequence();
				for (int j = start; j < start + sequence_length; j++) {
					testdata.add(new SequenceElement(_TESTDATA.get(fileindex)
							.get(j)));
					// testdata.getLast().State = 0;
					testdata.getLast().Repetition = 1;
				}
				// if (i%100 ==0)
				System.out.println("TEST " + (i + 1));
				out.write("TEST " + i);
				out.write("\n");
				out.write("TESTDATA           :" + testdata.toString());
				out.write("\n");
				out.write("   from" + start);
				out.write("\n");
				out.write("TEST REFINED       :"
						+ testdata.refineSequence().toString());
				out.write("\n");
				out.write("FIND MODE TEST DATA:" + findMode(testdata, 30));
				out.write("\n");
				out.write("FIND MODE REFINED  :"
						+ findMode(testdata.refineSequence(), 30));
				out.write("\n");
				out.write("BUSROUTE           :"
						+ _TESTDATA.get(fileindex).BusRouteID);
				out.write("\n");

				// hide the state
				// int compare = findMode(testdata, 30);
				System.out.println("BUSROUTE           :"
						+ _TESTDATA.get(fileindex).BusRouteID);
				testdata.BusRouteID = _TESTDATA.get(fileindex).BusRouteID;
				int compare = testdata.getLast().State;
				for (int j = 0; j < testdata.sequenceinFile.size(); j++) {
					testdata.get(j).State = 0;

				}
				out.write("TEST REFINED 222   :"
						+ testdata.refineSequence().toString());
				out.write("\n");

				// find busstop
				System.out.println(sm.refined_seqs.size() + " "
						+ testdata.refineSequence().toString());

				// version 1
				LinkedList<Character> result = sm.matchBusStop(testdata, out, CONSTANTS.ALLBUSROUTE);

				// version 2
				// LinkedList<Character> result;
				// int[] busRoute = sm.possibleBusRoute(testdata.get(0).Observation);
				// if (busRoute==null)
				// result = sm.matchBusStop(testdata, out, CONSTANTS.ALLBUSROUTE);
				// else
				// result = sm.matchBusStop(testdata, out, busRoute);
				

				out.write("RESULT             :");
				for (int j = 0; j < result.size(); j++) {
					out.write((int) result.get(j) + " ");
				}
				out.write("\n");

				out.write("COMPARE           :" + compare);
				out.write("\n");

				Utils.removeDuplicate(result);
				if (result.size() != 1) {
					++confusedCase;
					out.write("confused case\n");
				}

				// if (!isInArray(result, compare))
				if (!Utils.isInLinkedList(result, compare)) {
					out.write("====FAILED====\n\n\n\n");
					++countFalse;
				} else
					out.write("POSTITVE\n\n\n\n");

			}
			out.write("Number of test: " + CONSTANTS.nExample + "\n");
			out.write("Number of positive: "
					+ (CONSTANTS.nExample - countFalse) + "\n");
			out.write("Confused case: " + confusedCase + "\n");
			out.write("Accuracy: "
					+ (1.0 * (CONSTANTS.nExample - countFalse)
							/ CONSTANTS.nExample * 100.0) + "\n");

			// ===
			outSummary.write("Sequence length: " + sequence_length + "\n");
			outSummary.write("Number of test: " + CONSTANTS.nExample + "\n");
			outSummary.write("Number of positive: "
					+ (CONSTANTS.nExample - countFalse) + "\n");
			outSummary.write("Confused case: " + confusedCase + "\n");
			outSummary.write("Accuracy: "
					+ (1.0 * (CONSTANTS.nExample - countFalse)
							/ CONSTANTS.nExample * 100.0) + "\n");
			outSummary.write("Reference file name"
					+ (CONSTANTS.RESULT_FOLDER
							+ "busstopmatching_sequenceLength"
							+ sequence_length + ".txt\n"));
			outExcel.write(sequence_length + " " + CONSTANTS.nExample + " "
					+ (CONSTANTS.nExample - countFalse) + " " + confusedCase);

			out.close();

		} catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
		}

	}

	private int findMode(Sequence sequence, int count) {
		// System.out.println("MAX");

		if (count > sequence.size())
			count = sequence.size();
		int maxCount = 0;
		int maxState = 0;
		char key = 0;
		int value = 0;
		Hashtable<Character, Integer> countBusStop = new Hashtable<Character, Integer>();
		for (int i = sequence.size() - count; i < sequence.size(); i++) {
			key = sequence.get(i).State;
			if (countBusStop.containsKey(key)) {
				value = countBusStop.get(key) + 1;
				countBusStop.put(key, value);
			} else {
				value = 1;
				countBusStop.put(key, value);
			}
			if (value > maxCount) {
				maxCount = value;
				maxState = key;
			}
		}

		return maxState;
	}
}
